const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Main = imports.ui.main;
-const WindowManager = imports.ui.windowManager;
+const SwipeTracker = imports.ui.swipeTracker;
const Workspace = imports.ui.workspace;
var WORKSPACE_SWITCH_TIME = 250;
super._init(monitorIndex);
this._animating = false; // tweening
- this._scrolling = false; // swipe-scrolling
this._gestureActive = false; // touch(pad) gestures
this._scrollAdjustment = scrollAdjustment;
if (showAnimation) {
let easeParams = Object.assign(params, {
duration: WORKSPACE_SWITCH_TIME,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
});
// we have to call _updateVisibility() once before the
// animation and once afterwards - it does not really
for (let w = 0; w < this._workspaces.length; w++) {
let workspace = this._workspaces[w];
- if (this._animating || this._scrolling || this._gestureActive)
+ if (this._animating || this._gestureActive)
workspace.show();
else if (this._inDrag)
workspace.visible = Math.abs(w - active) <= 1;
workspaceManager.disconnect(this._reorderWorkspacesId);
}
- startSwipeScroll() {
- this._scrolling = true;
- }
-
- endSwipeScroll() {
- this._scrolling = false;
-
- // Make sure title captions etc are shown as necessary
- this._updateWorkspaceActors(true);
- this._updateVisibility();
- }
-
startTouchGesture() {
this._gestureActive = true;
}
this._workspace.syncStacking(stackIndices);
}
- startSwipeScroll() {
- }
-
- endSwipeScroll() {
- }
-
startTouchGesture() {
}
});
Main.overview.addAction(clickAction);
this.bind_property('mapped', clickAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
+ this._clickAction = clickAction;
- let panAction = new Clutter.PanAction({ threshold_trigger_edge: Clutter.GestureTriggerEdge.AFTER });
- panAction.connect('pan', this._onPan.bind(this));
- panAction.connect('gesture-begin', () => {
- if (this._workspacesOnlyOnPrimary) {
- let event = Clutter.get_current_event();
- if (this._getMonitorIndexForEvent(event) != this._primaryIndex)
- return false;
- }
-
- this._startSwipeScroll();
- return true;
- });
- panAction.connect('gesture-cancel', () => {
- clickAction.release();
- this._endSwipeScroll();
- });
- panAction.connect('gesture-end', () => {
- clickAction.release();
- this._endSwipeScroll();
- });
- Main.overview.addAction(panAction);
- this.bind_property('mapped', panAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
-
- let allowedModes = Shell.ActionMode.OVERVIEW;
- let switchGesture = new WindowManager.WorkspaceSwitchAction(allowedModes);
- switchGesture.connect('motion', this._onSwitchWorkspaceMotion.bind(this));
- switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this));
- switchGesture.connect('cancel', this._endTouchGesture.bind(this));
- Main.overview.addAction(switchGesture);
- this.bind_property('mapped', switchGesture, 'enabled', GObject.BindingFlags.SYNC_CREATE);
-
- switchGesture = new WindowManager.TouchpadWorkspaceSwitchAction(global.stage, allowedModes);
- switchGesture.connect('motion', this._onSwitchWorkspaceMotion.bind(this));
- switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this));
- switchGesture.connect('cancel', this._endTouchGesture.bind(this));
+ this._swipeTracker = new SwipeTracker.SwipeTracker(
+ Main.layoutManager.overviewGroup, Shell.ActionMode.OVERVIEW);
+ this._swipeTracker.connect('begin', this._switchWorkspaceBegin.bind(this));
+ this._swipeTracker.connect('update', this._switchWorkspaceUpdate.bind(this));
+ this._swipeTracker.connect('end', this._switchWorkspaceEnd.bind(this));
+ this.bind_property('mapped', this._swipeTracker, 'enabled', GObject.BindingFlags.SYNC_CREATE);
this._primaryIndex = Main.layoutManager.primaryIndex;
this._workspacesViews = [];
this._fullGeometry = null;
- this._scrolling = false; // swipe-scrolling
this._gestureActive = false; // touch(pad) gestures
this._canScroll = true; // limiting scrolling speed
}
_activeWorkspaceChanged(_wm, _from, _to, _direction) {
- if (this._scrolling)
+ if (this._gestureActive)
return;
this._scrollToActive();
}
_updateScrollAdjustment(index) {
- if (this._scrolling || this._gestureActive)
+ if (this._gestureActive)
return;
this._scrollAdjustment.ease(index, {
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
duration: WORKSPACE_SWITCH_TIME,
});
}
- _onPan(action) {
- let [dist_, dx, dy] = action.get_motion_delta(0);
- let adjustment = this._scrollAdjustment;
- if (global.workspace_manager.layout_rows == -1)
- adjustment.value -= (dy / this.height) * adjustment.page_size;
- else if (this.text_direction == Clutter.TextDirection.RTL)
- adjustment.value += (dx / this.width) * adjustment.page_size;
- else
- adjustment.value -= (dx / this.width) * adjustment.page_size;
- return false;
+ _directionForProgress(progress) {
+ if (global.workspace_manager.layout_rows === -1) {
+ return progress > 0
+ ? Meta.MotionDirection.DOWN
+ : Meta.MotionDirection.UP;
+ } else if (this.text_direction === Clutter.TextDirection.RTL) {
+ return progress > 0
+ ? Meta.MotionDirection.LEFT
+ : Meta.MotionDirection.RIGHT;
+ } else {
+ return progress > 0
+ ? Meta.MotionDirection.RIGHT
+ : Meta.MotionDirection.LEFT;
+ }
}
- _startSwipeScroll() {
- for (let i = 0; i < this._workspacesViews.length; i++)
- this._workspacesViews[i].startSwipeScroll();
- this._scrolling = true;
- }
+ _switchWorkspaceBegin(tracker, monitor) {
+ if (this._workspacesOnlyOnPrimary && monitor !== this._primaryIndex)
+ return;
- _endSwipeScroll() {
- for (let i = 0; i < this._workspacesViews.length; i++)
- this._workspacesViews[i].endSwipeScroll();
- this._scrolling = false;
- this._scrollToActive();
- }
+ let workspaceManager = global.workspace_manager;
+ let adjustment = this._scrollAdjustment;
+ if (this._gestureActive)
+ adjustment.remove_transition('value');
+
+ tracker.orientation = workspaceManager.layout_rows !== -1
+ ? Clutter.Orientation.HORIZONTAL
+ : Clutter.Orientation.VERTICAL;
- _startTouchGesture() {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].startTouchGesture();
- this._gestureActive = true;
- }
- _endTouchGesture() {
- for (let i = 0; i < this._workspacesViews.length; i++)
- this._workspacesViews[i].endTouchGesture();
- this._gestureActive = false;
- this._scrollToActive();
- }
+ let monitors = Main.layoutManager.monitors;
+ let geometry = monitor === this._primaryIndex
+ ? this._fullGeometry : monitors[monitor];
+ let distance = global.workspace_manager.layout_rows === -1
+ ? geometry.height : geometry.width;
- _onSwitchWorkspaceMotion(action, xRel, yRel) {
- // We don't have a way to hook into start of touchpad actions,
- // luckily this is safe to call repeatedly.
- this._startTouchGesture();
+ let progress = adjustment.value / adjustment.page_size;
+ let points = Array.from(
+ { length: workspaceManager.n_workspaces }, (v, i) => i);
- let workspaceManager = global.workspace_manager;
- let active = workspaceManager.get_active_workspace_index();
+ tracker.confirmSwipe(distance, points, progress, Math.round(progress));
+
+ this._gestureActive = true;
+ }
+
+ _switchWorkspaceUpdate(tracker, progress) {
let adjustment = this._scrollAdjustment;
- if (workspaceManager.layout_rows == -1)
- adjustment.value = (active - yRel / this.height) * adjustment.page_size;
- else if (this.text_direction == Clutter.TextDirection.RTL)
- adjustment.value = (active + xRel / this.width) * adjustment.page_size;
- else
- adjustment.value = (active - xRel / this.width) * adjustment.page_size;
+ adjustment.value = progress * adjustment.page_size;
}
- _onSwitchWorkspaceActivated(action, direction) {
+ _switchWorkspaceEnd(tracker, duration, endProgress) {
+ this._clickAction.release();
+
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
- let newWs = activeWorkspace.get_neighbor(direction);
- if (newWs != activeWorkspace)
- newWs.activate(global.get_current_time());
+ let newWs = workspaceManager.get_workspace_by_index(endProgress);
+
+ this._scrollAdjustment.ease(endProgress, {
+ mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
+ duration,
+ onComplete: () => {
+ if (newWs !== activeWorkspace)
+ newWs.activate(global.get_current_time());
+ this._endTouchGesture();
+ },
+ });
+ }
- this._endTouchGesture();
+ _endTouchGesture() {
+ for (let i = 0; i < this._workspacesViews.length; i++)
+ this._workspacesViews[i].endTouchGesture();
+ this._gestureActive = false;
}
vfunc_navigate_focus(from, direction) {
else
view = new WorkspacesView(i, this._scrollAdjustment);
- view.connect('scroll-event', this._onScrollEvent.bind(this));
-
// HACK: Avoid spurious allocation changes while updating views
view.hide();
}
_onScrollEvent(actor, event) {
+ if (this._swipeTracker.canHandleScrollEvent(event))
+ return Clutter.EVENT_PROPAGATE;
+
if (!this.mapped)
return Clutter.EVENT_PROPAGATE;